﻿///////////////////////////////////////////////////////////////////////////////
//	Copyright 2013 JASDev International
//
//	Licensed under the Apache License, Version 2.0 (the "License");
//	you may not use this file except in compliance with the License.
//	You may obtain a copy of the License at
//
//		http://www.apache.org/licenses/LICENSE-2.0
//
//	Unless required by applicable law or agreed to in writing, software
//	distributed under the License is distributed on an "AS IS" BASIS,
//	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//	See the License for the specific language governing permissions and
//	limitations under the License.
///////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections;
using System.Text;

namespace JDI.Pusher.Client
{
	internal class PusherEventEmitter
	{
		#region Constructors and IDisposable

		public PusherEventEmitter()
		{
			this.isDisposed = false;
			this.singleEventListeners = new Hashtable();
			this.globalEventListeners = new ArrayList();
		}

		~PusherEventEmitter()
		{
			this.Dispose(false);
		}

		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool isDisposing)
		{
			if (this.isDisposed)
				return;

			if (isDisposing)
			{
				// remove all listeners
				if (this.singleEventListeners != null)
				{
					foreach (DictionaryEntry entry in this.singleEventListeners)
					{
						for (int i = 0; i < ((ArrayList)entry.Value).Count; i++)
						{
							((ArrayList)entry.Value)[i] = null;
						}
					}
					this.singleEventListeners.Clear();
				}
				if (this.globalEventListeners != null)
				{
					for (int i = 0; i < this.globalEventListeners.Count; i++)
					{
						this.globalEventListeners[i] = null;
					}
					this.globalEventListeners.Clear();
				}
			}

			// set everything to null
			this.singleEventListeners = null;
			this.globalEventListeners = null;

			// make sure we don't dispose again
			this.isDisposed = true;
		}

		#endregion


		#region Methods

		public void Bind(string eventName, PusherDelegates.BindEventCallback callback)
		{
			if (this.singleEventListeners.Contains(eventName))
			{
				ArrayList list = ((ArrayList)this.singleEventListeners[eventName]);
				if (list.Contains(callback) == false)
					list.Add(callback);
			}
			else
			{
				ArrayList listeners = new ArrayList();
				listeners.Add(callback);
				this.singleEventListeners.Add(eventName, listeners);
			}
		}

		public void BindAll(PusherDelegates.BindEventCallback callback)
		{
			if (this.globalEventListeners.Contains(callback) == false)
				this.globalEventListeners.Add(callback);
		}

		public void UnBind(string eventName, PusherDelegates.BindEventCallback callback)
		{
			if (this.singleEventListeners.Contains(eventName))
			{
				ArrayList list = ((ArrayList)this.singleEventListeners[eventName]);
				list.Remove(callback);
				/* TODO - probably don't need this
				int index = 0;
				if ((index = list.IndexOf(callback)) >= 0)
				{
					list.RemoveAt(index);
				}
				*/
				if (list.Count == 0)
				{
					this.singleEventListeners.Remove(eventName);
				}
			}
		}

		public void UnBindAll(PusherDelegates.BindEventCallback callback)
		{
			this.globalEventListeners.Remove(callback);
		}

		public void EmitEvent(string eventName, string data = null)
		{
			// send event to global event listeners
			foreach (PusherDelegates.BindEventCallback callback in this.globalEventListeners)
			{
				callback(eventName, data);
			}

			// send event to single event listeners
			if (this.singleEventListeners.Contains(eventName))
			{
				foreach (PusherDelegates.BindEventCallback callback in ((ArrayList)this.singleEventListeners[eventName]))
				{
					callback(eventName, data);
				}
			}
		}

		#endregion


		protected bool isDisposed;
		private Hashtable singleEventListeners;
		private ArrayList globalEventListeners;
	}
}
